home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / dkbsrc.zip / IFF.C < prev    next >
C/C++ Source or Header  |  1991-04-30  |  14KB  |  347 lines

  1. /*****************************************************************************
  2. *
  3. *                                     iff.c
  4. *
  5. *   from DKBTrace (c) 1990  David Buck
  6. *
  7. *  This file implements a simple IFF format file reader.
  8. *
  9. * This software is freely distributable. The source and/or object code may be
  10. * copied or uploaded to communications services so long as this notice remains
  11. * at the top of each file.  If any changes are made to the program, you must
  12. * clearly indicate in the documentation and in the programs startup message
  13. * who it was who made the changes. The documentation should also describe what
  14. * those changes were. This software may not be included in whole or in
  15. * part into any commercial package without the express written consent of the
  16. * author.  It may, however, be included in other public domain or freely
  17. * distributed software so long as the proper credit for the software is given.
  18. *
  19. * This software is provided as is without any guarantees or warranty. Although
  20. * the author has attempted to find and correct any bugs in the software, he
  21. * is not responsible for any damage caused by the use of the software.  The
  22. * author is under no obligation to provide service, corrections, or upgrades
  23. * to this package.
  24. *
  25. * Despite all the legal stuff above, if you do find bugs, I would like to hear
  26. * about them.  Also, if you have any comments or questions, you may contact me
  27. * at the following address:
  28. *
  29. *     David Buck
  30. *     22C Sonnet Cres.
  31. *     Nepean Ontario
  32. *     Canada, K2H 8W7
  33. *
  34. *  I can also be reached on the following bulleton boards:
  35. *
  36. *     OMX              (613) 731-3419
  37. *     Mystic           (613) 596-4249  or  (613) 596-4772
  38. *
  39. *  Fidonet:   1:163/109.9
  40. *  Internet:  dbuck@ccs.carleton.ca
  41. *  The "You Can Call Me RAY" BBS    (708) 358-5611
  42. *
  43. *  IBM Port by Aaron A. Collins. Aaron may be reached on the following BBS'es:
  44. *
  45. *     The "You Can Call Me RAY" BBS (708) 358-5611
  46. *     The Information Exchange BBS  (708) 945-5575
  47. *
  48. *****************************************************************************/
  49.  
  50.  
  51. #include "frame.h"
  52. #include "dkbproto.h"
  53.  
  54. static IMAGE_COLOUR *iff_colour_map;
  55. static int colourmap_size;
  56. static CHUNK_HEADER Chunk_Header;
  57.  
  58. #define FORM 0x464f524dL
  59. #define ILBM 0x494c424dL
  60. #define BMHD 0x424d4844L
  61. #define CAMG 0x43414d47L
  62. #define CMAP 0x434d4150L
  63. #define BODY 0x424f4459L
  64. #define CMPNONE 0
  65.  
  66. #define HAM 0x800
  67.  
  68. void iff_error()
  69.    {
  70.    fprintf (stderr, "Invalid IFF file\n");
  71.    exit(1);
  72.    }
  73.  
  74. int read_byte(f)
  75.    FILE *f;
  76.    {
  77.    int c;
  78.    if ((c = getc(f)) == EOF)
  79.       iff_error();
  80.    return (c);
  81.    }
  82.  
  83. int read_word(f)
  84.    FILE *f;
  85.    {
  86.    int result;
  87.  
  88.    result = read_byte(f)*256;
  89.    result += read_byte(f);
  90.    return (result);
  91.    }
  92.  
  93. long read_long(f)
  94.    FILE *f;
  95.    {
  96.    int i;
  97.    long result;
  98.  
  99.    result = 0;
  100.    for (i = 0 ; i < 4 ; i++)
  101.       result = result * 256 + read_byte(f);
  102.  
  103.    return (result);
  104.    }
  105.  
  106. void Read_Chunk_Header (f, dest)
  107.    FILE *f;
  108.    CHUNK_HEADER *dest;
  109.    {
  110.    dest->name = read_long(f);
  111.    dest->size = read_long(f);
  112.    }
  113.  
  114. void Read_Iff_Image(Image, filename)
  115.    IMAGE *Image;
  116.    char *filename;
  117.    {
  118.    FILE *f;
  119.    unsigned char **row_bytes;
  120.    int c, i, j, k, nBytes, nPlanes, compression,
  121.        mask, byte_index, count, viewmodes;
  122.    int Previous_Red, Previous_Green, Previous_Blue;
  123.    struct Image_Line *line;
  124.    unsigned long creg;
  125.  
  126.    if ((f = Locate_File(filename, "rb")) == NULL) {
  127.       fprintf (stderr, "Cannot open IFF file %s\n", filename);
  128.       exit(1);
  129.       }
  130.  
  131.    Previous_Red = Previous_Green = Previous_Blue = 0;
  132.  
  133.    viewmodes = 0;
  134.    iff_colour_map = NULL;
  135.  
  136.    while (1) {
  137.       Read_Chunk_Header(f, &Chunk_Header);
  138.       switch ((int) Chunk_Header.name) {
  139.          case FORM:  if (read_long(f) != ILBM)
  140.                         iff_error();
  141.                      break;
  142.  
  143.          case BMHD:  Image->iwidth = read_word(f);
  144.                      Image->width = (DBL)Image->iwidth;
  145.                      Image->iheight = read_word(f);
  146.                      Image->height = (DBL)Image->iheight;
  147.  
  148.                      read_word(f);  /* x position ignored */
  149.                      read_word(f);  /* y position ignored */
  150.                      nPlanes = read_byte(f);
  151.                      colourmap_size = 1<<nPlanes;
  152.                      read_byte(f);   /* masking ignored */
  153.                      compression = read_byte(f);   /* masking ignored */
  154.                      read_byte(f);   /* pad */
  155.                      read_word(f);   /* Transparent colour ignored */
  156.                      read_word(f);   /* Aspect ratio ignored */
  157.                      read_word(f);   /* page width ignored */
  158.                      read_word(f);   /* page height ignored */
  159.                      break;
  160.  
  161.          case CAMG:  viewmodes = (int) read_long(f);   /* Viewmodes */
  162.                      if (viewmodes & HAM)
  163.                         colourmap_size = 16;
  164.  
  165.                      break;
  166.  
  167.          case CMAP:  colourmap_size = (int) Chunk_Header.size / 3;
  168.  
  169.                      if ((iff_colour_map = (IMAGE_COLOUR *) malloc(sizeof(IMAGE_COLOUR)*colourmap_size)) == NULL) {
  170.             fprintf(stderr, "Cannot allocate memory for IFF colour map\n");
  171.             exit(1);
  172.             }
  173.  
  174.                      for (i = 0 ; i < colourmap_size ; i++) {
  175.                         iff_colour_map[i].Red = read_byte(f);
  176.                         iff_colour_map[i].Green = read_byte(f);
  177.                         iff_colour_map[i].Blue = read_byte(f);
  178.                         iff_colour_map[i].Alpha = 0;
  179.                         }
  180.  
  181.                      Previous_Red = iff_colour_map[0].Red;
  182.                      Previous_Green = iff_colour_map[0].Green;
  183.                      Previous_Blue = iff_colour_map[0].Blue;
  184.                      for (i = colourmap_size * 3 ; (long) i < Chunk_Header.size ; i++)
  185.                         read_byte(f);
  186.  
  187.                      break;
  188.  
  189.          case BODY:  if ((iff_colour_map == NULL) || (viewmodes & HAM)) {
  190.                         Image->Colour_Map_Size = 0;
  191.                         Image->Colour_Map = NULL;
  192.                         }
  193.                      else {
  194.                         Image->Colour_Map_Size = colourmap_size;
  195.                         Image->Colour_Map = iff_colour_map;
  196.                         }
  197.  
  198.                      if ((row_bytes = (unsigned char **) malloc (4*nPlanes)) == NULL) {
  199.                         fprintf (stderr, "Cannot allocate memory for row bytes\n");
  200.                         exit(1);
  201.                         }
  202.  
  203.                      for (i = 0 ; i < nPlanes ; i++)
  204.                         if ((row_bytes[i] = (unsigned char *)
  205.                                         malloc((Image->iwidth+7)/8)) == NULL) {
  206.                fprintf (stderr, "Cannot allocate memory for row bytes\n");
  207.                            exit(1);
  208.                         }
  209.  
  210.                      if (Image->Colour_Map == NULL) {
  211.                         if ((Image->data.rgb_lines = (struct Image_Line *)
  212.                             malloc(Image->iheight * sizeof (struct Image_Line)))==NULL) {
  213.                            fprintf (stderr, "Cannot allocate memory for picture\n");
  214.                            exit(1);
  215.                            }
  216.                         }
  217.                      else {
  218.                         if ((Image->data.map_lines = (unsigned char **)
  219.                             malloc(Image->iheight * sizeof (unsigned char *)))==NULL) {
  220.                            fprintf (stderr, "Cannot allocate memory for picture\n");
  221.                            exit(1);
  222.                            }
  223.                         }
  224.  
  225.                      for (i = 0 ; i < Image->iheight ; i++) {
  226.  
  227.                         if (Image->Colour_Map == NULL) {
  228.                            if (((Image->data.rgb_lines[i].red = (unsigned char *)
  229.                                                  malloc(Image->iwidth))==NULL) ||
  230.                                ((Image->data.rgb_lines[i].green = (unsigned char *)
  231.                                                  malloc(Image->iwidth))==NULL) ||
  232.                                ((Image->data.rgb_lines[i].blue = (unsigned char *)
  233.                                                  malloc(Image->iwidth))==NULL)) {
  234.                               fprintf (stderr, "Cannot allocate memory for picture\n");
  235.                               exit(1);
  236.                               }
  237.                            }
  238.                         else {
  239.                            if ((Image->data.map_lines[i] = (unsigned char *)
  240.                                malloc(Image->iwidth * sizeof(unsigned char))) == NULL) {
  241.                               fprintf (stderr, "Cannot allocate memory for picture\n");
  242.                               exit(1);
  243.                               }
  244.                            }
  245.  
  246.                         for (j = 0 ; j < nPlanes ; j++)
  247.                            if (compression == CMPNONE) {
  248.                               for (k = 0 ; k < (Image->iwidth+7)/8 ; k++)
  249.                                  row_bytes[j][k] = (unsigned char)read_byte(f);
  250.                               if ((Image->iwidth & 7) != 0)
  251.                                  read_byte(f);
  252.                               }
  253.  
  254.                            else {
  255.                               nBytes = 0;
  256.                               while (nBytes != (Image->iwidth+7)/8) {
  257.                                  c = read_byte(f);
  258.                                  if ((c >= 0) && (c <= 127))
  259.                                     for (k = 0 ; k <= c ; k++)
  260.                                        row_bytes[j][nBytes++] = (unsigned char)read_byte(f);
  261.                                  else if ((c >= 129) && (c <= 255)) {
  262.                                     count = 257-c;
  263.                                     c = read_byte(f);
  264.                                     for (k = 0 ; k < count ; k++)
  265.                                        row_bytes[j][nBytes++] = (unsigned char)c;
  266.                                     }
  267.                                  }
  268.                               }
  269.  
  270.                         mask = 0x80;
  271.                         byte_index = 0;
  272.                         for (j = 0 ; j < Image->iwidth ; j++) {
  273.                            creg = 0;
  274.                            for (k = nPlanes-1 ; k >= 0 ; k--)
  275.                               if (row_bytes[k][byte_index] & mask)
  276.                                 creg = creg*2 + 1;
  277.                               else
  278.                                 creg *= 2;
  279.  
  280.  
  281.                            if (viewmodes & HAM) {
  282.                               line = &Image->data.rgb_lines[i];
  283.                               switch (creg >> 4) {
  284.                                  case 0:
  285.                                     Previous_Red = line->red[j] = (unsigned char)iff_colour_map[creg].Red;
  286.                                     Previous_Green = line->green[j] = (unsigned char)iff_colour_map[creg].Green;
  287.                                     Previous_Blue = line->blue[j] = (unsigned char)iff_colour_map[creg].Blue;
  288.                                     break;
  289.  
  290.                                  case 1:
  291.                                     line->red[j] = (unsigned char)Previous_Red;
  292.                                     line->green[j] = (unsigned char)Previous_Green;
  293.                                     line->blue[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  294.                                     Previous_Blue = (int) line->blue[j];
  295.                                     break;
  296.  
  297.                                  case 2:
  298.                                     line->red[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  299.                                     Previous_Red = (int) line->red[j];
  300.                                     line->green[j] = (unsigned char)Previous_Green;
  301.                                     line->blue[j] = (unsigned char)Previous_Blue;
  302.                                     break;
  303.  
  304.                                  case 3:
  305.                                     line->red[j] = (unsigned char)Previous_Red;
  306.                                     line->green[j] = (unsigned char)(((creg & 0xf)<<4) + (creg&0xf));
  307.                                     Previous_Green = (int) line->green[j];
  308.                                     line->blue[j] = (unsigned char)Previous_Blue;
  309.                                     break;
  310.                                  }
  311.                               }
  312.                            else if (nPlanes == 24) {
  313.                               line = &Image->data.rgb_lines[i];
  314.                               line->red[j] = (unsigned char)((creg >> 16) & 0xFF);
  315.                               line->green[j] = (unsigned char)((creg >> 8) & 0xFF);
  316.                               line->blue[j] = (unsigned char)(creg & 0xFF);
  317.                               }
  318.                            else {
  319.                               if (creg > (unsigned long)Image->Colour_Map_Size) {
  320.                                  fprintf (stderr, "Error - IFF Image Map Colour out of range\n");
  321.                                  exit(1);
  322.                                  }
  323.                               Image->data.map_lines[i][j] = (char)creg;
  324.                               }
  325.  
  326.                            mask >>= 1;
  327.                            if (mask == 0) {
  328.                               mask = 0x80;
  329.                               byte_index++;
  330.                               }
  331.                            }
  332.                         }
  333.  
  334.                      free (row_bytes);
  335.                      fclose (f);
  336.                      return;
  337.  
  338.          default:
  339.             for (i = 0 ; (long) i < Chunk_Header.size ; i++)
  340.                if (getc(f) == EOF)
  341.                   iff_error();
  342.             break;
  343.          }
  344.       }
  345.    }
  346.  
  347.